/*
 * This file is part of quickReminder, a software for gamers
 *
 * Copyright (C) 2006-2008 Lucas Romero
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
//using GA_ScreenScraper;
using ManagedWinapi.Windows;
using ManagedWinapi.Accessibility;
using HtmlAgilityPack;
using LucasCode.Win32;

namespace LucasCode.Tools
{
    public static class ESLHelpers
    {
        public class ParseException : Exception
        {
            public ParseException(string error)
                : base(error)
            {
                //relax
            }
            //nothing
        };

        public static string getMatchLink()
        {
            Trace.WriteLine("ESLHelpers: Entering getMatchLink()");
//#if !DEBUG
            try
            {
//#endif
                
                Trace.WriteLine("Trying to get matchlink from ESL Aequitas");
                //IntPtr handle = User32.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "ESL Aequitas *beta*", "ThunderRT6FormDC");
                //Trace.WriteLine(String.Format("Got handle {0} for aequitas window", handle));
                ManagedWinapi.Windows.SystemWindow aeqwin = new SystemWindow(IntPtr.Zero);
                foreach (SystemWindow w in aeqwin.AllChildWindows/*.AllDescendantWindows*/)
                {
                    if (w.Title.StartsWith("ESL Aequitas"))
                    {
                        foreach (SystemWindow w2 in w.AllChildWindows)
                        {
                            Debug.WriteLine("found '" + w2.Title + "' (class '" + w2.ClassName + "')");
                            if (w2.ClassName == "ThunderRT6TextBox")
                            {
                                Debug.WriteLine("FOUND AEQUITAS-MATCHLINK!");
                                SystemAccessibleObject stopmon = SystemAccessibleObject.FromWindow(w2, AccessibleObjectID.OBJID_WINDOW);
                                foreach (SystemAccessibleObject o in stopmon.Children)
                                    if (o.RoleIndex == 42)
                                    {
                                        Debug.WriteLine("Matchlink is: " + o.Value);
                                        return o.Value;
                                        //break;
                                    }
                                break;
                            }
                        }
                        break;
                    }
                }
//#if !DEBUG
            }
            catch(Exception ex)
            {
                Trace.WriteLine("ERROR while getting matchlink: " + ex.Message);
            }
//#endif
            Trace.WriteLine("ESLHelpers: Leaving getMatchLink()");
            return string.Empty;
        }

        public static string GetHTML(string URL, string cook)
        {
            return GetHTML(URL, new Cookie("COOKIE", cook, "/", ".esl.eu"));
        }
        public static string GetHTML(string URL, Cookie cook)
        {
            string HTML = String.Empty;
            HttpWebRequest request;
            HttpWebResponse response;
            StreamReader answer = null;
            request = (HttpWebRequest)WebRequest.Create(URL);
            request.Timeout = 10000;
            request.CookieContainer = new CookieContainer();
            request.CookieContainer.Add(cook);
            //get response
            
            try
            {
                response = (HttpWebResponse)request.GetResponse();
                answer = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                //while (m_UploadStatus != ItemUploadStatus.Aborted && answer.ReadLine() != String.Empty)
                //{
                //HTML += answer.ReadLine();
                //}
                HTML = answer.ReadToEnd();
                /*StreamWriter s = new StreamWriter("bla.txt");
                s.Write(HTML);
                s.Close();*/
            }
            catch (Exception ex)
            {
                //MessageBox.Show(ex.Message);
                HTML = String.Empty;
                return string.Empty;
            }
            finally
            {
                if(answer != null)
                    answer.Close();
            }
            return HTML;
        }
        public static bool isAequitasMonitoring()
        {
            Thread.Sleep(5000);
            SystemWindow[] ToplevelWindows = SystemWindow.AllToplevelWindows;
            foreach (SystemWindow win in ToplevelWindows)
            {
                //Debug.WriteLine(win.Title);
                if (win.Title.StartsWith("ESL Aequitas"))
                {
                    Debug.WriteLine("Untersuche " + win.HWnd.ToString());
                    SystemWindow[] controls = win.AllChildWindows;
                    foreach (SystemWindow control in controls)
                    {
                        //Debug.WriteLine(control.Title);
                        if (control.Title == "End Monitoring")
                            return control.Enabled;
                        //MessageBox.Show(control.Enabled ? "Running!" : "Not running!");
                    }
                }
            }
            return false;
        }


        public static bool isMatchInReach(TimeSpan before,TimeSpan after, string cookie, bool debug, StringCollection MatchFilter)
        {
            Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
            string html = String.Empty;

            
            bool opengame = false;
            HtmlAgilityPack.HtmlDocument d;
            try
            {
                Cookie cook = new Cookie("COOKIE", cookie, "/", ".esl.eu");
                //get html source
                html = GetHTML("http://www.esl.eu/change_lang/en/?ref=/open_matches/", cook);
                d = new HtmlAgilityPack.HtmlDocument();
                d.LoadHtml(html);
                //d.OptionOutputAsXml = true;
                //d.Save("esl.xml");
                //d.LoadHtml(HTML);
                //


                //datetime + login-status
                HtmlNode time = d.DocumentNode.SelectSingleNode(@"//div[@id=""datetime""]/div[2]");
                if (time == null)
                    throw new ParseException("Could not parse website header!");
                bool isLoggedIn = time.SelectSingleNode("b/a").Attributes["href"].Value.Trim().EndsWith("/logout/");
                if (!isLoggedIn)
                    throw new ParseException("Invalid login!");


                DateTime ServerTime = DateTime.MinValue;
                try
                {
                    HtmlNode ServerTimeNode = time.SelectSingleNode(@"//a[@id=""timezone""]");
                    string ServerTimeString = Regex.Match(ServerTimeNode.InnerText.Trim(), @"(\d\d\.\d\d\.\d\d \d\d:\d\d)h").Groups[1].Value;
                    ServerTimeString = ServerTimeString.Remove(ServerTimeString.Length - 1);
                    ServerTime = DateTime.Parse(ServerTimeString);
                }
                catch (Exception ex)
                {
                    throw new ParseException("Could not parse time: " + ex.Message);
                }

                //MessageBox.Show(ServerTime.ToString() + Environment.NewLine + isLoggedIn.ToString());

                HtmlNode matchinfos = d.DocumentNode.SelectSingleNode(@"//div[@id=""main_content""]");
                if (matchinfos == null)
                    throw new ParseException("Could not get main content!");

                HtmlNodeCollection matches = matchinfos.SelectNodes("div/table/tr[position()>=3]");
                
                //do we have some matches?
                if (matches != null)
                {
                    foreach (HtmlNode n in matches)
                    {
                        string datestr = n.SelectSingleNode("td[1]").InnerText.Trim();
                        //strip "Today, " or "Heute, " from string
                        datestr = datestr.Substring(datestr.IndexOf(',') + 1, datestr.Length - datestr.IndexOf(',') - 1);
                        DateTime matchdate = DateTime.Parse(datestr);

                        string enemy = n.SelectSingleNode("td[2]").InnerText.Trim();
                        string league = n.SelectSingleNode("td[5]/a").Attributes["href"].Value;

                        Trace.WriteLine(String.Format("Match vs. {0} on {1} found! ({2})", enemy, matchdate, league));

                        if (IsDateBetween(matchdate, ServerTime, before, after))
                        {
                            //opengame = true;
                            if (MatchFilter != null)
                                foreach (string filter in MatchFilter)
                                    if (Regex.Match(league, filter, RegexOptions.Singleline | RegexOptions.IgnoreCase).Success)
                                    {
                                        opengame = true;
                                        Trace.WriteLine(String.Format("Match vs. '{0}' on {1} matches filter '{2}'!", enemy, matchdate, filter));
                                        break;
                                    }
                        }
                    }
                }
                
                
                Trace.WriteLine("HTML DUMP:");
                Trace.WriteLine(html);
            }
            catch(Exception ex)
            {
                Trace.WriteLine("HTML DUMP:");
                Trace.WriteLine(html);
                throw ex;
            }
            return opengame;
            
        }


        /*public static bool isMatchInReach(TimeSpan before,TimeSpan after, string cookie, bool debug, StringCollection MatchFilter)
        {
            Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
            string html = String.Empty;
            */
            //const string prefilter = "<form action=\".*/open_matches/savesms/\" method=\"post\">.*?</form>";
            /*
            const string RecentMatchesRegex = @"\s\w*, (\d\d/\d\d/\d\d \d\d:\d\d)<.*?<a href="".*?((player)|(team))/\d+/"">(.*?)</a>.*<a.*?href=""(.*?/match/\d+/)"">Details</a>";
            const string SrvTimeRegex = @"<a.*?href=""/change_timezone/.*?"">(\d\d/\d\d/\d\d \d\d:\d\d)h.*?</a>";
            bool opengame = false;
            try
            {
                //debug filename
                //string filename = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "debug" + DateTime.Now.ToString().Replace(":", "-") + ".txt";

                //create cookie for login
                Cookie cook = new Cookie("COOKIE", cookie, "/", ".esl.eu");
                //get html source
                html = GetHTML("http://www.esl.eu/change_lang/en/?ref=/open_matches/", cook);

                //extract timestring from source
                string servertime = Regex.Match(html, SrvTimeRegex, RegexOptions.Singleline).Groups[1].Value;

                if (servertime == string.Empty)
                {
                    Trace.WriteLine("Could not parse ESL Website! Warning!");
                    throw new Exception("Could not parse ESL Website! Warning!");
                    return true;
                }

                //convert time from english MM/DD/YYYY to DD/MM/YYYY
                string servertime2 = servertime.Substring(3, 2) + "/" + servertime.Substring(0, 2) + servertime.Substring(5, servertime.Length - 5) + ":00";
                DateTime ServerTime = Convert.ToDateTime(servertime2);
                Trace.WriteLine("Time on ESL-Server: " + ServerTime.ToString());


                //strip garbage from html
                Match junk = Regex.Match(html, prefilter, RegexOptions.Singleline | RegexOptions.IgnoreCase);
                if (junk.Success)
                    html = junk.Value;

                MatchCollection matches = Regex.Matches(html, RecentMatchesRegex, RegexOptions.Singleline | RegexOptions.IgnoreCase);
                foreach (Match m in matches)
                {
                    //extract timestring from matchinfo
                    string s = m.Groups[1].Value;
                    //convert time from english MM/DD/YYYY to DD/MM/YYYY
                    string s2 = String.Format("{0}.{1}.{2}", s.Substring(3, 2), s.Substring(0, 2), s.Substring(6, 8));

                    string outstr = String.Format("MATCH vs. '{0}' @ {1} ({2}) in ladder '{3}'", m.Groups[5].Value, s, s2, m.Groups[6].Value);


                    Trace.WriteLine(outstr);

                    DateTime matchdate = Convert.ToDateTime(s2);
                    Trace.WriteLine("I think it's @" + matchdate.ToString());

                    TimeSpan t = ServerTime - matchdate;
                    Trace.WriteLine("Game is in " + t.Negate().ToString());
                    Trace.WriteLine("--------------------------------------------");
                    if (IsDateBetween(matchdate, ServerTime, before, after))
                    {
                        //opengame = true;
                        if (MatchFilter != null)
                            foreach (string filter in MatchFilter)
                                if (Regex.Match(m.Groups[6].Value, filter, RegexOptions.Singleline | RegexOptions.IgnoreCase).Success)
                                {
                                    opengame = true;
                                    Trace.WriteLine("Match matches filter '" + filter + "'!");
                                    break;
                                }
                        if (opengame)
                            break;
                    }
                }
                Trace.WriteLine("HTML DUMP:");
                Trace.WriteLine(html);
            }
            catch(Exception ex)
            {
                Trace.WriteLine("HTML DUMP:");
                Trace.WriteLine(html);
                throw ex;
            }
            return opengame;
            
        }*/
        private static bool IsDateBetween(DateTime a, DateTime start, DateTime end)
        {
            return (a >= start && a <= end);
        }
        private static bool IsDateBetween(DateTime target, DateTime a, TimeSpan before, TimeSpan after)
        {
            return (a >= target-before && a <= target+after);
        }
    }
}
